/**
 * Copyright 2010 Butin Kirill <kiryaka@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.flexupload.stream
{
	import flash.net.FileReference;
	
	import mx.rpc.events.ResultEvent;
	
	import org.flexupload.Flexupload;
	import org.flexupload.model.FileInfo;
	import org.flexupload.model.FilePart;
	import org.flexupload.model.ServerReply;
	import org.flexupload.remote.FlexuploadService;
	import org.flexupload.status.FileStatus;
	import org.flexupload.strategy.DevStrategy;

	public class FileStream
	{	
		private var fileInfo:FileInfo = new FileInfo();
		private var file:FileReference;
		private var threads:Array = new Array();
		private var finishedThreadCounter:int = 0;
		private var remoteService:FlexuploadService;
		private var fileStatus:FileStatus;
		
		public function FileStream(){}
		
		private function getByteArrayLength():int{
			return getStrategy().getByteArrayLength();
		}
		
		public function start(file:FileReference, remoteService:FlexuploadService):void{
			this.file = file;
			fileStatus = new FileStatus(file.name, file.size);
			fileInfo.init(file.name, file.size);
			this.remoteService = remoteService;
			
			this.remoteService.addEventListener(ResultEvent.RESULT, startUploadHandler);
			this.remoteService.startUpload(fileInfo);
		}
		
		public function createNewThread(remoteService:FlexuploadService):void{
			var threadStream:ThreadStream = new ThreadStream(this, remoteService);
			threads.push(threadStream);
		}		
		
		public function getFileStatus():FileStatus{
			return this.fileStatus;
		}
		
		private function startUploadHandler(event:ResultEvent):void{
			fileStatus.startCounting();
			
			var serverReply:ServerReply = ServerReply(event.result);
			if (serverReply.type != ServerReply.TYPE_START_UPLOAD ||
				serverReply.fileInfo.name != file.name ||
				serverReply.status != ServerReply.SUCCESS
			){
				return; // TODO (error processing and so on... all blocks like this)
			}
			fileInfo = serverReply.fileInfo;
			//trace("Start -- " +  fileInfo.toString());
			remoteService.removeEventListener(ResultEvent.RESULT, startUploadHandler);
			fileStatus.setTmpFileName(fileInfo.tempFileName);
			fileStatus.setProcessing();
			
			getStrategy().assignFreeSessions();
		}
		
		private function getStrategy():DevStrategy{
			return Flexupload.getInstance().getStrategy();
		}
		
		public function getFilePart():FilePart{
			if(file.data.bytesAvailable == 0) return null;
			var len:int = file.data.bytesAvailable > getByteArrayLength() ? getByteArrayLength() : file.data.bytesAvailable;
			var filePart:FilePart = new FilePart();
			var offset:int = file.data.length - file.data.bytesAvailable;
			file.data.readBytes(filePart.byteArray, 0, len);
			filePart.init(offset, len);
			return filePart;
		}		
		public function getFileInfo():FileInfo{
			return fileInfo;
		}
		public function finishThread():void{
			finishedThreadCounter++;
			if (finishedThreadCounter == threads.length) finishUpload();
		}
		private function finishUpload():void{
			remoteService.addEventListener(ResultEvent.RESULT, finishUploadHandler);
			remoteService.finishUpload(fileInfo);			
		}
		private function finishUploadHandler(event:ResultEvent):void{
			var serverReply:ServerReply = ServerReply(event.result);
			if (serverReply.type != ServerReply.TYPE_FINISH_UPLOAD ||
				serverReply.fileInfo.name != file.name ||
				serverReply.status != ServerReply.SUCCESS
			){
				return;
			}
			//trace("Finish: "+serverReply.fileInfo);
			fileStatus.setFinished();
			remoteService.removeEventListener(ResultEvent.RESULT, finishUploadHandler);
		}		
	}
}